/***************************************************************************
 *   Copyright (C) 2004 by Francisco J. Ros                                *
 *   fjrm@dif.um.es                                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

///
/// \file	AFSLS_state.cc
/// \brief	Implementation of all functions needed for manipulating the internal
///		state of an AFSLS node.
///

#include <mrmc_afsls/MRMC_AFSLS_state.h>
#include <mrmc_afsls/MRMC_AFSLS.h>

/********** MPR Selector Set Manipulation **********/

MrmcAFSLS_mprsel_tuple*
MrmcAFSLS_state::find_mprsel_tuple(nsaddr_t main_addr) {
	for (mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++) {
		MrmcAFSLS_mprsel_tuple* tuple = *it;
		if (tuple->main_addr() == main_addr)
			return tuple;
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_mprsel_tuple(MrmcAFSLS_mprsel_tuple* tuple) {
	for (mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++) {
		if (*it == tuple) {
			mprselset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::erase_mprsel_tuples(nsaddr_t main_addr) {
	for (mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++) {
		MrmcAFSLS_mprsel_tuple* tuple = *it;
		if (tuple->main_addr() == main_addr) {
			it = mprselset_.erase(it);
			it--;
		}
	}
}

void
MrmcAFSLS_state::insert_mprsel_tuple(MrmcAFSLS_mprsel_tuple* tuple) {
	mprselset_.push_back(tuple);
}

/********** Neighbor Set Manipulation **********/

MrmcAFSLS_nb_tuple*
MrmcAFSLS_state::find_nb_tuple(nsaddr_t main_addr) {
	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
		MrmcAFSLS_nb_tuple* tuple = *it;
		if (tuple->nb_main_addr() == main_addr)
			return tuple;
	}
	return NULL;
}

MrmcAFSLS_nb_tuple*
MrmcAFSLS_state::find_sym_nb_tuple(nsaddr_t main_addr) {
	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
		MrmcAFSLS_nb_tuple* tuple = *it;
		if (tuple->nb_main_addr() == main_addr && tuple->status() == MRMC_AFSLS_STATUS_SYM)
			return tuple;
	}
	return NULL;
}

MrmcAFSLS_nb_tuple*
MrmcAFSLS_state::find_nb_tuple(nsaddr_t main_addr, u_int8_t willingness) {
	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
		MrmcAFSLS_nb_tuple* tuple = *it;
		if (tuple->nb_main_addr() == main_addr && tuple->willingness() == willingness)
			return tuple;
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_nb_tuple(MrmcAFSLS_nb_tuple* tuple) {
	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
		if (*it == tuple) {
			nbset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::erase_nb_tuple(nsaddr_t main_addr) {
	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
		MrmcAFSLS_nb_tuple* tuple = *it;
		if (tuple->nb_main_addr() == main_addr) {
			it = nbset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::insert_nb_tuple(MrmcAFSLS_nb_tuple* tuple) {
	nbset_.push_back(tuple);
}

/********** Neighbor 2 Hop Set Manipulation **********/

MrmcAFSLS_nb2hop_tuple*
MrmcAFSLS_state::find_nb2hop_tuple(nsaddr_t nb_main_addr, nsaddr_t nb2hop_addr) {
	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
		MrmcAFSLS_nb2hop_tuple* tuple = *it;
		if (tuple->nb_main_addr() == nb_main_addr && tuple->nb2hop_addr() == nb2hop_addr)
			return tuple;
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_nb2hop_tuple(MrmcAFSLS_nb2hop_tuple* tuple) {
	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
		if (*it == tuple) {
			nb2hopset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::erase_nb2hop_tuples(nsaddr_t nb_main_addr, nsaddr_t nb2hop_addr) {
	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
		MrmcAFSLS_nb2hop_tuple* tuple = *it;
		if (tuple->nb_main_addr() == nb_main_addr && tuple->nb2hop_addr() == nb2hop_addr) {
			it = nb2hopset_.erase(it);
			it--;
		}
	}
}

void
MrmcAFSLS_state::erase_nb2hop_tuples(nsaddr_t nb_main_addr) {
	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
		MrmcAFSLS_nb2hop_tuple* tuple = *it;
		if (tuple->nb_main_addr() == nb_main_addr) {
			it = nb2hopset_.erase(it);
			it--;
		}
	}
}

/* 
 * Add by jt.zheng for MRMC 2011/01/11
 */
void
MrmcAFSLS_state::erase_nb2hop_tuples_by_nb2hop(nsaddr_t nb2hop_addr) {
	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
		MrmcAFSLS_nb2hop_tuple* tuple = *it;
		if (tuple->nb2hop_addr() == nb2hop_addr) {
			it = nb2hopset_.erase(it);
			it--;
		}
	}
}
/* END jt.zheng for MRMC */

void
MrmcAFSLS_state::insert_nb2hop_tuple(MrmcAFSLS_nb2hop_tuple* tuple){
	nb2hopset_.push_back(tuple);
}

/********** MPR Set Manipulation **********/

bool
MrmcAFSLS_state::find_mpr_addr(nsaddr_t addr) {
	mprset_t::iterator it = mprset_.find(addr);
	return (it != mprset_.end());
}

void
MrmcAFSLS_state::insert_mpr_addr(nsaddr_t addr) {
	mprset_.insert(addr);
}

void
MrmcAFSLS_state::clear_mprset() {
	mprset_.clear();
}

/********** Duplicate Set Manipulation **********/

MrmcAFSLS_dup_tuple*
MrmcAFSLS_state::find_dup_tuple(nsaddr_t addr, u_int16_t seq_num) {
	for (dupset_t::iterator it = dupset_.begin(); it != dupset_.end(); it++) {
		MrmcAFSLS_dup_tuple* tuple = *it;
		if (tuple->addr() == addr && tuple->seq_num() == seq_num)
			return tuple;
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_dup_tuple(MrmcAFSLS_dup_tuple* tuple) {
	for (dupset_t::iterator it = dupset_.begin(); it != dupset_.end(); it++) {
		if (*it == tuple) {
			dupset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::insert_dup_tuple(MrmcAFSLS_dup_tuple* tuple) {
	dupset_.push_back(tuple);
}

/********** Link Set Manipulation **********/

MrmcAFSLS_link_tuple*
MrmcAFSLS_state::find_link_tuple(nsaddr_t iface_addr) {
	for (linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++) {
		MrmcAFSLS_link_tuple* tuple = *it;
		if (tuple->nb_iface_addr() == iface_addr)
			return tuple;
	}
	return NULL;
}

MrmcAFSLS_link_tuple*
MrmcAFSLS_state::find_sym_link_tuple(nsaddr_t iface_addr, double now) {
	for (linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++) {
		MrmcAFSLS_link_tuple* tuple = *it;
		if (tuple->nb_iface_addr() == iface_addr) {
			if (tuple->sym_time() > now)
				return tuple;
			else
				break;
		}
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_link_tuple(MrmcAFSLS_link_tuple* tuple) {
	for (linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++) {
		if (*it == tuple) {
			linkset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::insert_link_tuple(MrmcAFSLS_link_tuple* tuple) {
	linkset_.push_back(tuple);
}

/********** Topology Set Manipulation **********/

MrmcAFSLS_topology_tuple*
MrmcAFSLS_state::find_topology_tuple(nsaddr_t dest_addr, nsaddr_t last_addr) {
	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
		MrmcAFSLS_topology_tuple* tuple = *it;
		if (tuple->dest_addr() == dest_addr && tuple->last_addr() == last_addr)
			return tuple;
	}
	return NULL;
}

MrmcAFSLS_topology_tuple*
MrmcAFSLS_state::find_newer_topology_tuple(nsaddr_t last_addr, u_int16_t ansn) {
	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
		MrmcAFSLS_topology_tuple* tuple = *it;
		if (tuple->last_addr() == last_addr && tuple->seq() > ansn)
			return tuple;
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_topology_tuple(MrmcAFSLS_topology_tuple* tuple) {
	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
		if (*it == tuple) {
			topologyset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::erase_older_topology_tuples(nsaddr_t last_addr, u_int16_t ansn) {
	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
		MrmcAFSLS_topology_tuple* tuple = *it;
		if (tuple->last_addr() == last_addr && tuple->seq() < ansn) {
			it = topologyset_.erase(it);
			it--;
		}
	}
}

void
MrmcAFSLS_state::insert_topology_tuple(MrmcAFSLS_topology_tuple* tuple) {
	topologyset_.push_back(tuple);
}

/********** Interface Association Set Manipulation **********/

MrmcAFSLS_iface_assoc_tuple*
MrmcAFSLS_state::find_ifaceassoc_tuple(nsaddr_t iface_addr) {
	for (ifaceassocset_t::iterator it = ifaceassocset_.begin();
		it != ifaceassocset_.end();
		it++) {
		MrmcAFSLS_iface_assoc_tuple* tuple = *it;
		if (tuple->iface_addr() == iface_addr)
			return tuple;
	}
	return NULL;
}

void
MrmcAFSLS_state::erase_ifaceassoc_tuple(MrmcAFSLS_iface_assoc_tuple* tuple) {
	for (ifaceassocset_t::iterator it = ifaceassocset_.begin();
		it != ifaceassocset_.end();
		it++) {
		if (*it == tuple) {
			ifaceassocset_.erase(it);
			break;
		}
	}
}

void
MrmcAFSLS_state::insert_ifaceassoc_tuple(MrmcAFSLS_iface_assoc_tuple* tuple) {
	ifaceassocset_.push_back(tuple);
}


/*
 *	Add by jt.zheng for MRMC AFSLS 2011/01/11
 */
void
MrmcAFSLS_state::unique_nbset() {

	for(nbset_t::iterator it1 = nbset_.begin(); it1 != nbset_.end(); it1++) {
		for(nbset_t::iterator it2 = it1+1; it2 != nbset_.end();) {
			
			if( (*it1)->nb_main_addr() == (*it2)->nb_main_addr() ) {
				it2 = nbset_.erase(it2);
			}
			else
				it2++;
	
		}
	}
	
}

void
MrmcAFSLS_state::unique_nb2hopset() {

	for(nb2hopset_t::iterator it1 = nb2hopset_.begin(); 
		it1 != nb2hopset_.end(); 
		it1++) {
		
		for(nb2hopset_t::iterator it2 = it1+1; it2 != nb2hopset_.end();) {
			
			if( (*it1)->nb2hop_addr() == (*it2)->nb2hop_addr() ) {
				it2 = nb2hopset_.erase(it2);
			}
			else
				it2++;
	
		}
	}
	
}

void
MrmcAFSLS_state::unique_mprselset() {

	for(mprselset_t::iterator it1 = mprselset_.begin(); 
		it1 != mprselset_.end(); 
		it1++) {
		
		for(mprselset_t::iterator it2 = it1+1; it2 != mprselset_.end();) {
			
			if( (*it1)->main_addr() == (*it2)->main_addr() ) {
				it2 = mprselset_.erase(it2);
			}
			else
				it2++;
	
		}
	}
	
}
/* END jt.zheng 2011/01/11 */
